package com.songxh.core.config;

import com.alibaba.fastjson.JSON;
import com.songxh.core.annotation.Cache;
import com.songxh.core.base.CommonResult;
import com.songxh.core.shared.constant.RedisConsts;
import com.songxh.core.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author songxh
 * @create 2023-01-17-14:10
 */
@Aspect
@Component
@Slf4j
public class CacheAspectConfig {

    //切入点 所有使用Cache注解的方法
    @Pointcut("@annotation(com.songxh.core.annotation.Cache)")
    public void cut(){}

    @Around("cut()")
    public Object around(ProceedingJoinPoint point) {
        try {
            Signature signature = point.getSignature();
            //调用的方法名
            String methodName = signature.getName();

            Object[] args = point.getArgs();//参数
            Class[] parameterTypes = new Class[args.length];//参数类型，就是获取那一串包名
            //参数
            String params = "";
            for(int i=0; i<args.length; i++) {
                if(args[i] != null) {
                    params += JSON.toJSONString(args[i]);
                    parameterTypes[i] = args[i].getClass();
                }else {
                    parameterTypes[i] = null;
                }
            }
            if (StringUtils.isNotEmpty(params)) {
                //加密 以防出现key过长以及字符转义获取不到的情况
                params = DigestUtils.md5Hex(params);
            }
            Method method = point.getSignature().getDeclaringType().getMethod(methodName, parameterTypes);
            //获取Cache注解
            Cache annotation = method.getAnnotation(Cache.class);
            //过期时间
            int expire = annotation.expire();
            //名称
            String name = annotation.name();
            //获取redis的key
            String cacheKey = String.format(RedisConsts.S_CACHE_INFO_KEY, name, methodName, params);
            //查看缓存中是否存在该数据
            String value = RedisUtils.get(cacheKey, String.class);
            if (StringUtils.isNotEmpty(value)){
                return JSON.parseObject(value, CommonResult.class);
            }
            //如果不存在数据 那么就正常流程走一遍方法并将结果存入缓存
            Object proceed = point.proceed();
            RedisUtils.set(cacheKey, JSON.toJSONString(proceed), expire);
            return proceed;
        }catch (Throwable throwable){
            throwable.printStackTrace();
        }
        return CommonResult.failure("缓存时出现错误");
    }

}
